Modeling
Conjoint Analysis

An Introduction to the Hierarchical Bayesian Multinominal Logit

Bowen Hickman and Marc Dotson

Conjoint

Predicting new product success

In order to predict new product success, you need to estimate product demand

  • New (hypothetical) products don’t exist and can’t be used in a test market
  • We can ask people their preferences, but stated preferences are unreliable
  • If people are bad at stating preferences, they’re good at making choices, so let’s us get at their revealed preferences
  • If you can estimate product demand as a function of product features and price, you can design a new product that you can expect to succeed

Conjoint analysis is a survey-based experiment for estimating product demand where product features and price are evaluated jointly (i.e., conjointly)

  • Products are defined by attributes, each with a number of levels
  • Respondents choose from among product alternatives
  • Respondent-level preferences are estimated for each attribute level
  • Preference estimates are used to make counterfactual predictions in a simulated market
  • Market simulators inform new product development, pricing, product line optimization, etc.

Multilevel Modeling

\[ \Large{U_{hj} = \beta_{h1}x_{j1} + \beta_{h2}x_{j2} + \cdots + \beta_{hk}x_{jk} + \epsilon_{hj}} \]

\[ \Large{\color{grey}{U_{hj} = \beta_{h1}\color{black}{x_{j1}} + \beta_{h2}\color{black}{x_{j2}} + \cdots + \beta_{hk}\color{black}{x_{jk}} + \epsilon_{hj}}} \]

\[ \Large{\color{grey}{U_{hj} = \color{black}{\beta_{h1}}x_{j1} + \color{black}{\beta_{h2}}x_{j2} + \cdots + \color{black}{\beta_{hk}}x_{jk} + \epsilon_{hj}}} \]

\[ \Large{\color{grey}{U_{hj} = \color{black}{\beta_{\color{red}{h}1}}x_{j1} + \color{black}{\beta_{\color{red}{h}2}}x_{j2} + \cdots + \color{black}{\beta_{\color{red}{h}k}}x_{jk} + \epsilon_{hj}}} \]

Complete pooling

Groups have the same parameters from one model

Partial pooling

Each group has their own parameters but they pool information in one model

No pooling

Each group has their own parameters from separate models

Bayesian Inference

Comparing frequentist and Bayesian inference

Frequentist

  • Data \(X, Y\) are random variables
  • Parameter estimates are point estimates
  • Confidence intervals are a collection of theoretical point estimates

Bayesian

  • Parameters \(\beta\) are random variables
  • Parameter estimates are posterior distributions
  • Credible intervals are summaries of posterior distributions

Logistic regression

\[ \large{y_{j} \sim \text{Binomial}(1, p_{j})} \\ \large{\log\left({p_{j} \over 1 - p_{j}}\right) = \beta_{0} + \beta_{1} x_{j1} + \cdots + \beta_{p} x_{jp}} \]

  • Logistic regression is a generalized linear model (GLM) for binary outcomes
  • Instead of modeling the mean of a normal distribution, we’re modeling the probability of getting a 1
  • Every GLM has a link function for the linear model, and this is the logit link function

Bayesian logistic regression

# Frequentist logistic regression
bin_mod = smf.glm(
  'y ~ x1 + x2 + x3', 
  data = conjoint_data,
  family = sm.families.Binomial()
)

# Bayesian logistic regression
bin_mod = bmb.Model(
  'y ~ x1 + x2 + x3', 
  data = conjoint_data,
  family = 'bernoulli'
)

bin_mod
       Formula: y ~ x1 + x2 + x3
        Family: bernoulli
          Link: p = logit
  Observations: 500
        Priors: 
    target = p
        Common-level effects
            Intercept ~ Normal(mu: 0.0, sigma: 1.5)
            x1 ~ Normal(mu: 0.0, sigma: 0.3476)
            x2 ~ Normal(mu: 0.0, sigma: 2.0006)
            x3 ~ Normal(mu: 0.0, sigma: 0.4888)

Multinomial Logit

Multinomial logit

\[ \large{y_{j} \sim \text{Multinomial}(n_{jk}, p_{jk})} \\ \large{\log\left({p_{jk} \over \sum_k p_{jk}}\right) = \beta_{0} + \beta_{1} x_{j1} + \cdots + \beta_{p} x_{jp}} \]

  • The multinomial logit is a generalization of logistic regression
  • Also referred to as multinomial logistic regression, multiclass logistic regression, and categorical regression
  • The outcome is a categorical variable with more than two categories

Bayesian multinomial logit

# Bayesian multinomial logit
cat_mod = bmb.Model(
  'y ~ x1 + x2 + x3', 
  data = conjoint_data,
  family = 'categorical'
)

cat_mod
       Formula: y ~ x1 + x2 + x3
        Family: categorical
          Link: p = softmax
  Observations: 500
        Priors: 
    target = p
        Common-level effects
            Intercept ~ Normal(mu: 0.0, sigma: 10.8786)
            x1 ~ Normal(mu: 0.0, sigma: 0.8005)
            x2 ~ Normal(mu: 0.0, sigma: 5.0048)
            x3 ~ Normal(mu: 0.0, sigma: 1.2736)

Hierarchical Multinomial Logit

Hierarchical multinomial logit

\[ \large{y_{hj} \sim \text{Multinomial}(n_{jk}, p_{hjk})} \\ \large{\log\left({p_{hjk} \over \sum_k p_{hjk}}\right) = \beta_{h0} + \beta_{h1} x_{j1} + \cdots + \beta_{hp} x_{jp}} \]

  • A hierarchical model is a multilevel model where the outcomes are nested (e.g., choices nested within respondents)
  • The hierarchical multinomial logit (HMNL) is a generalization of hierarchical logistic regression
  • The outcome is a categorical variable with more than two categories where there are multiple outcomes per group (e.g., multiple choices per respondent)

Bayesian HMNL

We can have all of our parameters vary by group (i.e., random effects)

# Specify a Bayesian hierarchical multinomial logit
hmnl_mod = bmb.Model(
  'y ~ (x1 + x2 + x3 | group)', 
  data = conjoint_data,
  family = 'categorical'
)

hmnl_mod
       Formula: y ~ (x1 + x2 + x3 | group)
        Family: categorical
          Link: p = softmax
  Observations: 500
        Priors: 
    target = p
        Common-level effects
            Intercept ~ Normal(mu: 0.0, sigma: 2.5)
        
        Group-level effects
            1|group ~ Normal(mu: 0.0, sigma: HalfNormal(sigma: 2.5))
            x1|group ~ Normal(mu: 0.0, sigma: HalfNormal(sigma: 0.8005))
            x2|group ~ Normal(mu: 0.0, sigma: HalfNormal(sigma: 5.0048))
            x3|group ~ Normal(mu: 0.0, sigma: HalfNormal(sigma: 1.2736))

Bayesian HMNL

Or we can have some parameters vary by group and some not (i.e., mixed effects)

# Specify a Bayesian hierarchical multinomial logit
hmnl_mod = bmb.Model(
  'y ~ (1 | group) + x1 + x2 + x3', 
  data = conjoint_data,
  family = 'categorical'
)

hmnl_mod
       Formula: y ~ (1 | group) + x1 + x2 + x3
        Family: categorical
          Link: p = softmax
  Observations: 500
        Priors: 
    target = p
        Common-level effects
            Intercept ~ Normal(mu: 0.0, sigma: 10.8786)
            x1 ~ Normal(mu: 0.0, sigma: 0.8005)
            x2 ~ Normal(mu: 0.0, sigma: 5.0048)
            x3 ~ Normal(mu: 0.0, sigma: 1.2736)
        
        Group-level effects
            1|group ~ Normal(mu: 0.0, sigma: HalfNormal(sigma: 10.8786))